<template>
  <div>test</div>
</template>

<script>
export default {
  data() {
    return {
      testData: [
        {
          label: "一级 1",
          children: [
            {
              label: "二级 1-1",
              children: [
                {
                  label: "三级 1-1-1"
                }
              ]
            }
          ]
        },
        {
          label: "一级 2",
          children: [
            {
              label: "二级 2-1",
              children: [
                {
                  label: "三级 2-1-1"
                }
              ]
            },
            {
              label: "二级 2-2",
              children: [
                {
                  label: "三级 2-2-1"
                }
              ]
            }
          ]
        },
        {
          label: "一级 3",
          children: [
            {
              label: "二级 3-1",
              children: [
                {
                  label: "三级 3-1-1"
                }
              ]
            },
            {
              label: "二级 3-2",
              children: [
                {
                  label: "三级 3-2-1"
                }
              ]
            }
          ]
        }
      ]
    };
  },
  methods: {
    show() {}
  },
  created() {
    //
    let nodeIdSeed = 0;
    const NODE_KEY = "$treeNodeId";

    const getPropertyFromData = function(node) {
      const data = node.data || {};
      return data["children"] || "";
    };
    const markNodeData = function(node, data) {
      if (!data || data[NODE_KEY]) return;
      Object.defineProperty(data, NODE_KEY, {
        value: node.id,
        enumerable: false,
        configurable: false,
        writable: false
      });
    };

    class Node {
      constructor(options) {
        this.id = nodeIdSeed++;
        this.text = null;
        this.checked = false;
        this.indeterminate = false;
        this.data = null;
        this.expanded = false;
        this.parent = null;
        this.visible = true;
        this.isCurrent = false;

        for (let name in options) {
          // eslint-disable-next-line no-prototype-builtins
          if (options.hasOwnProperty(name)) {
            this[name] = options[name];
          }
        }

        // internal
        this.level = 0;
        this.loaded = false;
        this.childNodes = [];
        this.loading = false;

        if (this.parent) {
          this.level = this.parent.level + 1;
        }

        // const store = this.store;

        if (this.data) {
          this.setData(this.data);
        }
        if (!Array.isArray(this.data)) {
          markNodeData(this, this.data);
        }
      }
      getChildren(forceInit = false) {
        // this is data
        if (this.level === 0) return this.data;
        const data = this.data;
        if (!data) return null;

        const props = this.store.props;
        let children = "children";
        if (props) {
          children = props.children || "children";
        }

        if (data[children] === undefined) {
          data[children] = null;
        }

        if (forceInit && !data[children]) {
          data[children] = [];
        }

        return data[children];
      }
      insertChild(child, index) {
        if (!child) throw new Error("insertChild error: child is required.");

        if (!(child instanceof Node)) {
          //   if (!batch) {
          //     const children = this.getChildren(true);
          //     if (children.indexOf(child.data) === -1) {
          //       if (typeof index === "undefined" || index < 0) {
          //         children.push(child.data);
          //       } else {
          //         children.splice(index, 0, child.data);
          //       }
          //     }
          //   }
          Object.assign(child, {
            parent: this,
            store: this.store
          });
          child = new Node(child);
        }

        // child.level = this.level + 1;

        if (typeof index === "undefined" || index < 0) {
          this.childNodes.push(child);
        } else {
          this.childNodes.splice(index, 0, child);
        }
      }
      // ..
      setData(data) {
        if (!Array.isArray(data)) {
          markNodeData(this, data);
        }

        this.data = data;
        this.childNodes = [];

        let children;
        if (this.level === 0 && this.data instanceof Array) {
          children = this.data;
        } else {
          children = getPropertyFromData(this) || [];
        }

        for (let i = 0, j = children.length; i < j; i++) {
          this.insertChild({ data: children[i] });
        }
      }
    }

    class TreeStore {
      constructor(options) {
        this.data = options.data;
        this.key = options.nodeKey;
        this.test = "11";
        this.root = new Node({
          data: this.data,
          store: this
        });
      }
    }

    this.store = new TreeStore({
      data: this.testData
    });

    console.log(this.store);
  }
};
</script>
